home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
vsoup11.zip
/
nntpcl.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-02
|
16KB
|
715 lines
// $Id: nntpcl.cc 1.14 1996/09/02 13:28:02 hardy Exp $
//
// This progam/module was written by Hardy Griech based on ideas and
// pieces of code from Chin Huang (cthuang@io.org). Bug reports should
// be submitted to rgriech@ibm.net.
//
// This file is part of soup++ for OS/2. Soup++ including this file
// is freeware. There is no warranty of any kind implied. The terms
// of the GNU Gernal Public Licence are valid for this piece of software.
//
// NNTP client routines
//
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "mts.hh"
#include "nntp.hh"
#include "nntpcl.hh"
#include "socket.hh"
//
// is this a misfeature of GCC, is there a better way to do it??
//
#define STR2(x) #x
#define STR(x) STR2(x)
static TSemaphor cntSema; // static in class tut nicht (gcc2.7.0)
static TProtCounter bytesRcvd;
//--------------------------------------------------------------------------------
TNntp::TNntp( void )
{
#ifdef TRACE_ALL
printfT( "TNntp::TNntp()\n" );
#endif
tmpF = NULL;
tmpN = NULL;
xrefHook = NULL;
killQHook = NULL;
actGroup = xstrdup("");
selGroup = xstrdup("");
user = xstrdup("");
passwd = xstrdup("");
strcpy( lastErrMsg, "unknown error condition" );
} // TNntp::TNntp
TNntp::~TNntp()
{
#ifdef TRACE_ALL
printfT( "TNntp::~TNntp()\n" );
#endif
close( 0 );
//// delete actGroup;
//// delete selGroup;
//// delete user;
//// delete passwd;
} // TNntp::~TNntp
void TNntp::setHelper( void (*xref)(const char *xrefLine),
int (*killQ)(const char *groupName, const char *headerLine ) )
{
xrefHook = xref;
killQHook = killQ;
} // TNntp::setHelper
TNntp::Res TNntp::request( const char *cmd, char *reply, size_t replySize,
int expReply )
//
// Send a request to NNTP server and check the result (cmd must not end with \n)
// If the server request authentication, the AUTHINFO procedure according to
// RFC977-extension will be executed.
//
{
int retcode;
int loopCnt;
*reply = '\0';
loopCnt = 0;
for (;;) {
//
// three retries for the command
//
if (loopCnt++ >= 3) {
strcpy( lastErrMsg,"nntp server is in a loop requesting AUTHINFO..." );
return nok;
}
//
// transmit the command & fetch the result
//
puts( cmd );
if (gets(reply,replySize) == NULL) {
sprintfT( lastErrMsg,"%s: no reply", cmd );
return nok;
}
bytesRcvd += strlen(reply);
if (reply[0] == CHAR_FATAL) {
sprintfT( lastErrMsg,"%s: fatal(%s)", cmd,reply );
return nok;
}
//
// if return code != ERR_NOAUTH, we are done (-> check the result)
//
retcode = atoi(reply);
if (retcode != ERR_NOAUTH)
break;
#ifndef NDEBUG
fprintfT( stderr,"authentication requested\n" );
#endif
//
// otherwise do the authentication
//
printf( "AUTHINFO USER %s\n",user );
if (gets(reply,replySize) == NULL) {
strcpy( lastErrMsg,"AUTHINFO USER: no reply" );
return nok;
}
retcode = atoi(reply);
if (retcode == OK_AUTH)
continue;
if (retcode != NEED_AUTHDATA) {
sprintfT( lastErrMsg,"AUTHINFO USER: %s",reply );
return nok;
}
printf( "AUTHINFO PASS %s\n",passwd );
if (gets(reply,replySize) == NULL) {
strcpy( lastErrMsg,"AUTHINFO PASS: no reply" );
return nok;
}
retcode = atoi(reply);
if (retcode != OK_AUTH) {
sprintfT( lastErrMsg,"AUTHINFO PASS: %s",reply );
return nok;
}
#ifndef NDEBUG
fprintfT( stderr,"authentication ok\n" );
#endif
}
if (retcode != expReply) {
sprintfT( lastErrMsg,"%s: %s", cmd,reply );
return nok;
}
return ok;
} // TNntp::request
TNntp::Res TNntp::open( const char *nntpServer, const char *nntpUser,
const char *nntpPasswd )
{
char buf[NNTP_STRLEN];
int response;
#ifdef TRACE_ALL
printfT( "TNntp::open(%s)\n",nntpServer );
#endif
readOnly = 0;
xstrdup( &user,nntpUser );
xstrdup( &passwd,nntpPasswd );
if (nntpServer == NULL || *nntpServer == '\0') {
strcpy( lastErrMsg,"no news server defined" );
return nok;
}
if (TSocket::open( nntpServer,"nntp","tcp" ) < 0) {
strcpy( lastErrMsg,"cannot open socket" );
return nok;
}
if (gets(buf, sizeof(buf)) == NULL) {
strcpy( lastErrMsg,"connect: no reply" );
#ifdef DEBUG
printfT( "TNntp::open(): socket: %s\n",buf );
#endif
return nok;
}
else {
response = atoi(buf);
switch (response) {
case OK_NOPOST:
readOnly = 1;
break;
case OK_CANPOST:
break;
case ERR_ACCESS:
sprintfT( lastErrMsg,"connect: no permission, %s",buf );
return nok;
default:
sprintfT( lastErrMsg,"connect: ill response, %s",buf );
#ifdef DEBUG
printfT( "TNntp::open(): illresp: %s\n",buf );
#endif
return nok;
}
}
//
// This is for INN (result is ignored)
//
request( "MODE READER",buf,sizeof(buf),OK_CANPOST );
#ifdef DEBUG_ALL
printfT( "TNntp::open(): antwort auf mode reader: %s\n",buf );
#endif
//
// create temporary file
//
if (tmpF == NULL) {
sysSema.Request();
tmpN = tempnam(NULL,"soup");
tmpF = fopenT(tmpN,"w+b");
sysSema.Release();
if (tmpF == NULL) {
sprintfT( lastErrMsg,"create of '%s' failed",tmpN );
return nok;
}
}
return ok;
} // TNntnp::open
void TNntp::close( int sendQuit )
{
#ifdef TRACE_ALL
printfT( "TNntp::close(%d)\n",sendQuit );
#endif
if (sendQuit) {
char buf[100];
#ifdef TRACE_ALL
printfT( "TNntp::close(): QUIT\n" );
#endif
request( "QUIT",buf,sizeof(buf), OK_GOODBYE );
TSocket::close();
}
//
// remove temporary file
//
if (tmpF != NULL) {
fcloseT( tmpF );
tmpF = NULL;
removeT( tmpN );
//// delete tmpN;
tmpN = NULL;
}
} // TNntp::close
const char *TNntp::getLastErrMsg( void )
{
return lastErrMsg;
} // TNntp::getLastErrMsg
TNntp::Res TNntp::getNewGroups( const char *nntpTimeFile, int changeFile )
//
// - send listing of new newsgroups as an email
// - add new newsgroups to newsrc
//
{
char oldTime[80], nntpTime[80], buf[NNTP_STRLEN];
FILE *dateF;
int getall;
char *p;
#ifdef TRACE
printfT( "getNewGroups()\n" );
#endif
//
// get current date/time from NNTP server
//
if (request("DATE",buf,sizeof(buf),INF_DATE) == ok)
sscanfT( buf+4, "%s", nntpTime );
else {
time_t now = time(NULL);
strftime( nntpTime, sizeof(nntpTime), "%Y%m%d%H%M%S", gmtime(&now) );
}
//
// Get last date/time we checked for new newsgroups.
//
getall = 0;
if ((dateF = fopenT(nntpTimeFile, "r")) != NULL) {
fgetsT( oldTime, sizeof(oldTime), dateF);
fclose( dateF );
}
else {
//
// This is probably the first we checked for new newsgroups.
// yes -> get all available newsgroups!
//
memset( oldTime,0,sizeof(oldTime) );
getall = 1;
}
//
// Request new newsgroups.
//
{
char cmd[100];
if (getall)
strcpy( cmd,"LIST" );
else
sprintfT( cmd,"NEWGROUPS %-6.6s %-6.6s GMT", oldTime+2, oldTime+8);
if (request(cmd,buf,sizeof(buf),getall ? OK_GROUPS : OK_NEWGROUPS) != ok)
return nok;
}
ftruncateT( tmpF,0L );
while (gets(buf, sizeof(buf)) != NULL) {
#ifdef DEBUG_ALL
printfT( "rcv: %s\n",buf );
#endif
bytesRcvd += strlen(buf)+1;
if (buf[0] == '.')
break;
if ((p = strchr(buf, ' ')) != NULL)
*p = '\0';
fputsT( buf,tmpF );
fputcT( '\n',tmpF );
}
//
// Save current date/time.
//
if (changeFile) {
if ((dateF = fopenT(nntpTimeFile,"w")) != NULL) {
fprintfT( dateF,"%s\n",nntpTime );
fcloseT(dateF);
}
}
return ok;
} // TNntp::getNewGroups
TNntp::Res TNntp::getOverview( long first, long last )
//
// Attention: those overview lines are sometimes VERY long (ref